#include <iostream>
#include <unistd.h>
#include <cassert>
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define PROCESS_NUM 10
#define MAKE_SEED() srand((unsigned long)time(nullptr))

typedef void (*func_t)();

void downLoadTask()
{
    std::cout << getpid() << ": 下载任务\n"
              << std::endl;
    sleep(1);
}

void ioTask()
{
    std::cout << getpid() << ": IO任务\n"
              << std::endl;
    sleep(1);
}

void flushTask()
{
    std::cout << getpid() << ": 刷新任务\n"
              << std::endl;
    sleep(1);
}

void Load_Task(std::vector<func_t> *funcMap)
{
    assert(funcMap);
    funcMap->push_back(downLoadTask);
    funcMap->push_back(ioTask);
    funcMap->push_back(flushTask);
    funcMap->push_back(flushTask);
}

class SubEp
{
public:
    SubEp(pid_t subid, int writefd)
        : _subid(subid), _writefd(writefd)
    {
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "process-%d[pid(%d)-fd(%d)]", num++, _subid, _writefd);
        _name = buffer;
    }

public:
    static int num;
    std::string _name;
    pid_t _subid;
    int _writefd;
};
int SubEp::num = 0;

int Rec_Task(int readFd)
{
    int code = 0;
    ssize_t n = read(readFd, &code, sizeof(code));
    if (n == 4)
        return code;
    else if (n <= 0)
        return -1;
    else
        return 0;
}
void Creat_subprocess(std::vector<SubEp> *subs, std::vector<func_t> &funcMap)
{
    std::vector<int> deleteFd;
    for (int i = 0; i < PROCESS_NUM; i++)
    {
        int fds[2];
        int n = pipe(fds);
        assert(n == 0);
        pid_t pid = fork();
        assert(pid >= 0);
        (void)n;
        if (pid == 0)
        {
            // 这是子进程
            for (size_t i = 0; i < deleteFd.size(); i++)
                close(deleteFd[i]);
            close(fds[1]);
            while (true)
            {
                // 从父进程里读
                int Command_code = Rec_Task(fds[0]);
                if (Command_code >= 0 && Command_code < funcMap.size())
                    funcMap[Command_code]();
                else if (Command_code == -1)
                    break;
            }
            exit(0);
        }
        // 这是父进程,通过匿名管道给子进程信息。
        close(fds[0]);
        SubEp sub(pid, fds[1]);
        subs->push_back(sub);
        deleteFd.push_back(sub._writefd);
    }
}
void SendTask(const SubEp &Process, int Tasknum)
{
    std::cout << "send task num: " << Tasknum << "send to -> " << Process._name << std::endl;
    int n = write(Process._writefd, &Tasknum, sizeof(Tasknum));
    assert(n == sizeof(int));
    (void)n;
}

void loadBlanceContrl(const std::vector<SubEp> &subs, const std::vector<func_t> &funcMap, int count)
{
    int processnum = subs.size();
    int funcnum = funcMap.size();
    bool forver = (count == 0 ? true : false);
    while (true)
    {
        int subIndex = rand() % processnum;
        int taskIndex = rand() % funcnum;
        SendTask(subs[subIndex], taskIndex);
        sleep(1);
        if (!forver)
        {
            count--;
            if (count == 0)
                break;
        }
    }
    for (int i = 0; i < processnum; i++)
        close(subs[i]._writefd);
}

void waitProcess(std::vector<SubEp> &processes)
{
    int processnums = processes.size();
    for (int i = 0; i < processnums; i++)
    {
        waitpid(processes[i]._subid, nullptr, 0);
        std::cout << "wait sub process success ...: " << processes[i]._subid << std::endl;
    }
}

int main()
{
    MAKE_SEED();
    std::vector<SubEp> subs;
    std::vector<func_t> funcMap;
    Load_Task(&funcMap);
    Creat_subprocess(&subs, funcMap);
    int count = 11;
    loadBlanceContrl(subs, funcMap, count);
    waitProcess(subs);
    return 0;
}